﻿using System;
using System.Reactive.Linq;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using Medecine.DataAccess.Observations;
using Medecine.Interface.Main;
using Medecine.Interface.Properties;
using System.Reactive.Threading;
using Medecine.Dbo;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.IO;

namespace Medecine.Interface.Observations
{
	public class AddObservationViewModel : ViewModelWithErrors
	{
		public AddObservationViewModel(int patientId)
		{
			_patientId = patientId;
			_observation = new Observation();
			_observation.Date = DateTime.Now;
			_dropCommand = new RelayCommand<DragEventArgs>(Drop, CanDrop);
			_addCommand = new RelayCommand(Add);
			_cancelCommand = new RelayCommand(Cancel);
		}

		private readonly int _patientId;

		#region Observation

		private readonly Observation _observation;
		public Observation Observation
		{
			get { return _observation; }
		}

		public DateTime Date
		{
			get { return _observation.Date; }
			set
			{
				if (_observation.Date == value)
					return;
				_observation.Date = value;
				RaisePropertyChanged("Date");
			}
		}

		public int Weight
		{
			get { return _observation.Weight; }
			set
			{
				if (_observation.Weight == value)
					return;
				_observation.Weight = value;
				RaisePropertyChanged("Weight");
			}
		}

		public int BloodPressure
		{
			get { return _observation.BloodPressure; }
			set
			{
				if (_observation.BloodPressure == value)
					return;
				_observation.BloodPressure = value;
				RaisePropertyChanged("BloodPressure");
			}
		}

		public string Comment
		{
			get { return _observation.Comment; }
			set
			{
				if (_observation.Comment == value)
					return;
				_observation.Comment = value;
				RaisePropertyChanged("Comment");
			}
		}

		public string[] Prescription
		{
			get { return _observation.Prescription; }
			set
			{
				if (_observation.Prescription == value)
					return;
				_observation.Prescription = value;
				RaisePropertyChanged("Prescription");
			}
		}

		#endregion // Observation

		#region Pictures

		private readonly ObservableCollection<byte[]> _pictures = new ObservableCollection<byte[]>();
		public ObservableCollection<byte[]> Pictures { get { return _pictures; } }

		#region Drop

		private readonly RelayCommand<DragEventArgs> _dropCommand = null;
		public RelayCommand<DragEventArgs> DropCommand { get { return _dropCommand; } }

		private bool CanDrop(DragEventArgs dragData)
		{
			return dragData.Data != null;
		}

		private void Drop(DragEventArgs dragData)
		{
			string[] fileArray = (string[])dragData.Data.GetData(DataFormats.FileDrop);
			foreach (string file in fileArray)
			{
				if ((Path.GetExtension(file) == ".jpg")
					|| (Path.GetExtension(file) == ".jpeg")
					|| (Path.GetExtension(file) == ".png"))
				{
					using (FileStream stream = new FileStream(file, FileMode.Open))
					{
						BinaryReader reader = new BinaryReader(stream);
						Pictures.Add(reader.ReadBytes((int)stream.Length));
					}
				}
			}
		}

		#endregion // Drop

		#endregion // Pictures

		#region Add

		private readonly RelayCommand _addCommand;
		public RelayCommand AddCommand { get { return _addCommand; } }

		private void Add()
		{
			_observation.Pictures = Pictures.ToArray();

			using (ServiceObservationClient service = new ServiceObservationClient())
			{
				Observable.FromAsyncPattern<int, Observation, bool>(service.BeginAddObservation, service.EndAddObservation)
					.Invoke(_patientId, Observation)
					.ObserveOnDispatcher()
					.Subscribe(AddCompleted, (e) => Messenger.Default.Send(new ErrorMessage(e.Message)));
			}
		}

		private void AddCompleted(bool result)
		{
			if (result == false)
				Messenger.Default.Send(new ErrorMessage(Resources.AddObservationError));
			else
			{
				Cancelled = false;
				Messenger.Default.Send(new GoToViewMessage(ViewName.Home));
			}
		}

		#endregion // Add

		#region Cancel

		private bool _cancelled = true;
		public bool Cancelled
		{
			get { return _cancelled; }
			private set { _cancelled = value; }
		}

		private readonly RelayCommand _cancelCommand;
		public RelayCommand CancelCommand { get { return _cancelCommand; } }

		private void Cancel()
		{
			Messenger.Default.Send(new GoToViewMessage(ViewName.Home));
		}

		#endregion // Cancel
	}
}
